package cn.net.lwj.common.util;

import cn.net.lwj.common.model.JsonResult;
import cn.net.lwj.common.model.XmlResult;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class XmlXStreamUtils {

    /**
     * 对象转XML
     * @param obj 需要转换的对象
     * @param aliasMap 对象的别名集合
     * @return
     */
    @SuppressWarnings("unchecked")
    public static String objectToXml(Object obj,Map<String,Class<?>> aliasMap){
        XStream xStream=new XStream(new DomDriver());
        if(aliasMap!=null&&aliasMap.size()>0){
            Iterator<String> it = aliasMap.keySet().iterator();
            while(it.hasNext()){
                String key = it.next();
                xStream.alias(key, aliasMap.get(key));
            }
        }

        //xStream.useAttributeFor(DataSjjhView.class, "xmlnsXsi");
        //xStream.aliasField("xmlns:xsi", DataSjjhView.class, "xmlnsXsi");
        xStream.autodetectAnnotations(true);//开启xstream的注解扫描

        xStream.aliasSystemAttribute(null, "class");

        xStream.registerConverter(new BlobConverter());
        xStream.registerConverter(new NullToXmlConverter());
        xStream.registerConverter(new IntegerConverter());
        xStream.registerConverter(new DateConverter());

        //xStream.registerConverter(new DoubleConverter());
//		System.out.println(obj==null?null:"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"+xStream.toXML(obj));
        return  obj==null?null:"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"+xStream.toXML(obj);
    }

    public static String objectToXml(Object obj, Map<String, Class<?>> aliasMap, List<XmlIgnoreField> ignoreFields) {
        XStream xStream = new XStream(new DomDriver());
        if (aliasMap != null && aliasMap.size() > 0) {
            Iterator<String> it = aliasMap.keySet().iterator();
            while (it.hasNext()) {
                String key = it.next();
                xStream.alias(key, aliasMap.get(key));
            }
        }
        if (ignoreFields != null && ignoreFields.size() > 0) {
            for (XmlIgnoreField ignoreField : ignoreFields) {
                xStream.omitField(ignoreField.getClazz(), ignoreField.getField());
            }
        }
        //xStream.useAttributeFor(DataSjjhView.class, "xmlnsXsi");
        //xStream.aliasField("xmlns:xsi", DataSjjhView.class, "xmlnsXsi");
        xStream.autodetectAnnotations(true);//开启xstream的注解扫描
        xStream.aliasSystemAttribute(null, "class");
        xStream.registerConverter(new BlobConverter());
        xStream.registerConverter(new NullToXmlConverter());
        xStream.registerConverter(new IntegerConverter());
        xStream.registerConverter(new DateConverter());

        //xStream.registerConverter(new DoubleConverter());
//		System.out.println(obj==null?null:"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"+xStream.toXML(obj));
        return obj == null ? null : "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n" + xStream.toXML(obj);
    }
    /**
     * XML转JAVA对象
     * @param xml XML格式的字符串
     * @return
     */
    @SuppressWarnings("unchecked")
    public static Object xmlToObject(String xml,Map<String,Class<?>> aliasMap){
        //XStream xStream=new XStream(new DomDriver());
        XStream xStream=new XStream(new DomDriver("UTF-8"));
        if (aliasMap != null && aliasMap.size() > 0) {
            for (String key : aliasMap.keySet()) {
                xStream.alias(key, aliasMap.get(key));
            }
        }
        //xStream.omitField(Class definedIn, String fieldName);
        //反序列化时这个注解不生效  延迟加载
        xStream.autodetectAnnotations(true);//开始xstream的注解扫描
        xStream.registerConverter(new DateConverter());

        xStream.registerConverter(new BlobConverter());
        xStream.registerConverter(new NullToXmlConverter());
        xStream.registerConverter(new IntegerConverter());
        xStream.registerConverter(new DateConverter());

        return xml==null||xml.trim().equals("")?null:xStream.fromXML(xml);
    }

    /**
     * 反序列化必须通过调用processAnnotations()来开启注解，不能通过autodetectAnnotations()开启 ！！！
     *
     * @param xml
     * @param clazz
     * @return
     */
    public static Object xmlToObject(String xml, Class<?> clazz, Map<String, Class<?>> aliasMap) {
        XStream xStream = new XStream(new DomDriver());
        if (aliasMap != null && aliasMap.size() > 0) {
            for (String key : aliasMap.keySet()) {
                xStream.alias(key, aliasMap.get(key));
            }
        }
        //xStream.omitField(Class definedIn, String fieldName);
        //反序列化时这个注解不生效  延迟加载
        //xStream.autodetectAnnotations(true);//开始xstream的注解扫描
        xStream.processAnnotations(clazz);
        xStream.registerConverter(new DateConverter());
        xStream.registerConverter(new BlobConverter());
        xStream.registerConverter(new NullToXmlConverter());
        xStream.registerConverter(new IntegerConverter());
        xStream.registerConverter(new DateConverter());
        return xml == null || xml.trim().equals("") ? null : xStream.fromXML(xml);
    }
    public static Object xmlToObject(String xml, Class<?> clazz) {
        XStream xStream = new XStream(new DomDriver());
        //xStream.omitField(Class definedIn, String fieldName);
        //反序列化时这个注解不生效  延迟加载
        //xStream.autodetectAnnotations(true);//开始xstream的注解扫描
        xStream.processAnnotations(clazz);
        xStream.registerConverter(new DateConverter());
        xStream.registerConverter(new BlobConverter());
        xStream.registerConverter(new NullToXmlConverter());
        xStream.registerConverter(new IntegerConverter());
        xStream.registerConverter(new DateConverter());
        return xml == null || xml.trim().equals("") ? null : xStream.fromXML(xml);
    }

    /**
     * XML转JAVA对象
     *
     * @return
     */
    @SuppressWarnings("unchecked")
    public static Object xmlToObject(InputStream in, Map<String, Class> aliasMap) {
        XStream xStream = new XStream(new DomDriver());
        if (aliasMap != null && aliasMap.size() > 0) {
            Iterator<String> it = aliasMap.keySet().iterator();
            while (it.hasNext()) {
                String key = it.next();
                xStream.alias(key, aliasMap.get(key));
            }
        }
        xStream.registerConverter(new BlobConverter());
        //xStream.registerConverter(new NullFromXmlConverter());
        xStream.registerConverter(new IntegerConverter());
        xStream.registerConverter(new DateConverter());

        return in == null ? null : xStream.fromXML(in);
    }

    public static void writeData(String wjdata, String parentPath,String fileName) throws Exception {
        //处理特殊字符
        wjdata = wjdata.replace("&#xd;", "").replace("&#x1a;", "").replace("&#x1c;", "").replace("&#x7;", "");
        File file = new File(parentPath);
        if (!file.exists()) {
            file.mkdirs();
        }
        String wjPath = parentPath + File.separator + fileName;
        if (parentPath.endsWith(File.separator)) {
            wjPath = parentPath + fileName;
        }
        try (OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream(wjPath, false), StandardCharsets.UTF_8)) {
            out.write(wjdata);
            out.flush();
        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception("写文件错误！");
        }
    }


   /* *//**
     * 转换xml字符串为map
     * @author LiuYang
     * @param xml
     * @return
     * @throws Exception
     *//*
    public static Map<String, Object> parseXml(String xml) throws Exception{
        if(xml==null||xml.trim().equals("")){
            return new HashMap<>();
        }
        SAXReader reader = new SAXReader();
        StringReader sr = new StringReader(xml);
        InputSource is = new InputSource(sr);
        Document document = reader.read(is);
        Element root = document.getRootElement();
        Map<String,Object> map = new HashMap<>();
        for (Element child : root.elements()) {
            if (child.elements().size() == 0) {
                map.put(child.getName(), child.getTextTrim());
            } else {
                List<String> lst = new ArrayList<>();
                for (Element child2 : child.elements()) {
                    lst.add(child2.getTextTrim());
                }
                map.put(child.getName(), lst);
            }
        }
        return map;
    }

    *//**
     * 转换map为xml字符串
     *
     * @param map
     * @return
     * @author LiuYang
     *//*
    public static String createXml(Map<String, Object> map, String rootName) {
        org.dom4j.Document document = DocumentHelper.createDocument();
        rootName = rootName == null || "".equals(rootName) ? map.getClass().getName() : rootName;
        org.dom4j.Element root = document.addElement(rootName);
        for (String key : map.keySet()) {
            org.dom4j.Element child = root.addElement(key);
            if (map.get(key) instanceof List) {
                child.setName(key + "List");
                List lst = (List) map.get(key);
                for (Object str : lst) {
                    child.addElement(key).setText(str.toString());
                }
            } else
                child.setText(map.get(key).toString());
        }
        return document.asXML();
    }

    *//**
     *
     * @param
     * @param
     * @return
     *//*
    public static String mapToXml(Map<String, Object> map, String rootName) {
        Document document = DocumentHelper.createDocument();
        rootName = rootName == null || "".equals(rootName) ? map.getClass().getName() : rootName;
        Element root = document.addElement(rootName);
        for (String key : map.keySet()) {
            Element child = root.addElement(key);
            if (map.get(key) instanceof List) {
                child.setName(key + "List");
                List lst = (List) map.get(key);
                for (Object obj : lst) {
                    Map<String, Object> temp = (Map<String, Object>) obj;
                    addListMapElement(temp, child, key);
                }
            } else if (map.get(key) instanceof Map) {
                addMapElement((Map<String, Object>) map.get(key), child);
            } else {
                child.setText(map.get(key).toString());
            }
        }
        //String ss = document.asXML();
        return document.asXML();
    }

    public static void addListMapElement(Map<String, Object> map, Element element, String rootName) {
        rootName = rootName == null || "".equals(rootName) ? map.getClass().getName() : rootName;
        Element child = element.addElement(rootName);
        for (String key : map.keySet()) {
            Element secendChild = child.addElement(key);
            secendChild.setName(key);
            secendChild.setText(map.get(key).toString());
        }
    }

    public static void addMapElement(Map<String, Object> map, Element element) {
        for (String key : map.keySet()) {
            Element secendChild = element.addElement(key);
            secendChild.setName(key);
            secendChild.setText(map.get(key).toString());
        }
    }*/

    public static void main(String[] args) {
        JsonResult jsonResult = new JsonResult();
        jsonResult.setStatus(200);
        jsonResult.setMsg("成功");
        jsonResult.setData("哈哈哈");
        String xml = XmlXStreamUtils.objectToXml(jsonResult, null);
        System.out.println(xml);
        List<XmlIgnoreField> ignoreFields = new ArrayList<>();
        ignoreFields.add(new XmlIgnoreField(JsonResult.class, "data"));
        ignoreFields.add(new XmlIgnoreField(JsonResult.class, "msg"));
        ignoreFields.add(new XmlIgnoreField(XmlResult.class, "msg"));
        String xml1 = XmlXStreamUtils.objectToXml(jsonResult, null,ignoreFields);
        System.out.println(xml1);
    }

}
